package net.xdclass.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import net.xdclass.config.RabbitMQConfig;
import net.xdclass.entity.Product;
import net.xdclass.entity.ProductTask;
import net.xdclass.enums.BizCodeEnum;
import net.xdclass.enums.ProductOrderStateEnum;
import net.xdclass.enums.StockTaskStateEnum;
import net.xdclass.exception.BizException;
import net.xdclass.feign.ProductOrderFeignService;
import net.xdclass.mapper.ProductMapper;
import net.xdclass.mapper.ProductTaskMapper;
import net.xdclass.model.ProductMessage;
import net.xdclass.request.LockProductRequest;
import net.xdclass.request.OrderItemRequest;
import net.xdclass.service.IProductService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import net.xdclass.utils.JsonData;
import net.xdclass.vo.ProductVO;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author lixin
 * @since 2024-09-02
 */
@Service
@Slf4j
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements IProductService {

    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private ProductTaskMapper productTaskMapper;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private RabbitMQConfig rabbitMQConfig;

    @Autowired
    private ProductOrderFeignService orderFeignService;

    /**
     * 分页查询商品列表
     *
     * @param page
     * @param size
     * @return
     */
    @Override
    public Map<String, Object> page(int page, int size) {

        Page<Product> pageInfo = new Page<>(page, size);

        Page<Product> productPage = productMapper.selectPage(pageInfo, null);

        Map<String, Object> pageMap = new HashMap<>(3);
        pageMap.put("total_record", productPage.getTotal());
        pageMap.put("total_page", productPage.getPages());
        pageMap.put("current_data", productPage.getRecords().stream().map(obj -> beanProcess(obj)).collect(Collectors.toList()));
        return pageMap;
    }

    /**
     * 根据id找商品详情
     *
     * @param productId
     * @return
     */
    @Override
    public ProductVO findById(long productId) {
        Product product = productMapper.selectById(productId);
        return beanProcess(product);
    }


    /**
     * 批量查询
     *
     * @param productIdList
     * @return
     */
    @Override
    public List<ProductVO> findProductsByBatch(List<Long> productIdList) {

        List<Product> productList = productMapper.selectList(new QueryWrapper<Product>().in("id", productIdList));

        List<ProductVO> productVOList = productList.stream().map(obj -> beanProcess(obj)).collect(Collectors.toList());
        return productVOList;
    }

    /**
     * 锁定商品库存
     * 1.遍历商品，锁定每个商品购买数量
     * 2.每一次锁定的时候，都要发送延迟消息
     *
     * @param lockProductRequest
     * @return
     */
    @Override
    public JsonData lockProductStock(LockProductRequest lockProductRequest) {

        List<OrderItemRequest> orderItemList = lockProductRequest.getOrderItemList();
        String orderOutTradeNo = lockProductRequest.getOrderOutTradeNo();

        //商品id
        List<Long> productIdList = orderItemList.stream().map(OrderItemRequest::getProductId).collect(Collectors.toList());

        //批量查询
        List<ProductVO> productVOList = this.findProductsByBatch(productIdList);
        //分组
        Map<Long, ProductVO> productMap = productVOList.stream().collect(Collectors.toMap(ProductVO::getId, Function.identity()));

        for (OrderItemRequest item : orderItemList) {
            //锁定商品记录
            int rows = productMapper.lockProductStock(item.getProductId(), item.getBuyNum());
            if (rows != 1) {
                //失败
                throw new BizException(BizCodeEnum.ORDER_CONFIRM_LOCK_PRODUCT_FAIL);
            }
            {
                //锁定成功
                //task表插入记录
                ProductTask productTask = new ProductTask();
                ProductVO productVO = productMap.get(item.getProductId());
                productTask.setProductId(item.getProductId());
                productTask.setBuyNum(item.getBuyNum());
                productTask.setLockState(StockTaskStateEnum.LOCK.name());
                productTask.setProductName(productVO.getTitle());
                productTask.setOutTradeNo(orderOutTradeNo);
                productTaskMapper.insert(productTask);
                log.info("商品库存锁定-插入product_task成功 :{}", productTask);

                //发送延迟消息，解锁商品库存
                ProductMessage productMessage = new ProductMessage();
                productMessage.setOutTradeNo(orderOutTradeNo);
                productMessage.setTaskId(productTask.getId());
                rabbitTemplate.convertAndSend(rabbitMQConfig.getEventExchange(), rabbitMQConfig.getStockReleaseDelayRoutingKey(), productMessage);
                log.info("商品库存锁定信息延迟消息发送成功: {}", productMessage);
            }
        }
        return JsonData.buildSuccess();
    }

    /**
     * 释放商品库存
     *
     * @param productMessage
     * @return
     */
    @Override
    public boolean releaseProductStock(ProductMessage productMessage) {
        //查询工作单是否存在
        ProductTask productTask = productTaskMapper.selectOne(new QueryWrapper<ProductTask>().eq("id", productMessage.getTaskId()));
        if (productTask == null) {
            log.warn("工作单不存在，消息体为: {}", productMessage);
        }

        //lock状态才处理
        if (productTask.getLockState().equalsIgnoreCase(StockTaskStateEnum.LOCK.name())) {
            //查询订单状态
            JsonData jsonData = orderFeignService.queryProductOrderState(productMessage.getOutTradeNo());

            if (jsonData.getCode() == 0) {

                String state = jsonData.getData().toString();

                if (ProductOrderStateEnum.NEW.name().equalsIgnoreCase(state)) {
                    //订单为NEW状态，返回给消息队列重新投递
                    log.warn("订单为NEW状态，返回给消息队列重新投递 :{}", productMessage);
                    return false;
                }

                if (ProductOrderStateEnum.PAY.name().equalsIgnoreCase(state)) {
                    //订单为已支付状态PAY，修改task状态为FINISH
                    productTask.setLockState(StockTaskStateEnum.FINISH.name());
                    productTaskMapper.update(productTask, new QueryWrapper<ProductTask>().eq("id", productMessage.getTaskId()));
                    log.info("订单已支付，修改库存锁定工作单FINISH状态 :{}", productMessage);
                    return true;
                }
            }

            //订单不存在,或者订单被取消,确认消息，修改task为CANCEL，恢复商品库存
            log.warn("订单不存在,或者订单被取消,确认消息,修改task为CANCEL， 恢复商品库存, message:{}", productMessage);
            productTask.setLockState(StockTaskStateEnum.CANCEL.name());
            productTaskMapper.update(productTask, new QueryWrapper<ProductTask>().eq("id", productMessage.getTaskId()));

            //恢复商品库存，即锁定库存减去当前购买的数量
            productMapper.unlockProductStock(productTask.getProductId(), productTask.getBuyNum());

            return true;

        } else {
            //非lock状态
            log.warn("工作单不是LOCK状态, state={}, 消息体", productTask.getLockState(), productMessage);
        }

        return false;
    }

    private ProductVO beanProcess(Product product) {
        ProductVO productVO = new ProductVO();
        BeanUtils.copyProperties(product, productVO);
        productVO.setStock(product.getStock() - product.getLockStock());
        return productVO;
    }
}
